﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Onuprova.Anaglyphing.ImageProcessor;

namespace _3D_Processor
{
    public partial class CalibrationWindow : Form
    {
        public CalibrationWindow()
        {
            InitializeComponent();
        }

        #region Form handlers
        private void CalibrationWindow_Load(object sender, EventArgs e)
        {
            adjustmentButtons1.AdjustmentChanged += new AdjustmentParameterChangedEventHandler(LeftButtonHandler);
            adjustmentButtons2.AdjustmentChanged += new AdjustmentParameterChangedEventHandler(RightButtonHandler);
            ImageSizeCombo.SelectedIndex = Properties.Settings.Default.CalibrationWindowSize;
        }

        private void CalibrationWindow_FormClosed(object sender, FormClosedEventArgs e)
        {
            adjustmentButtons1.AdjustmentChanged -= new AdjustmentParameterChangedEventHandler(LeftButtonHandler);
            adjustmentButtons2.AdjustmentChanged -= new AdjustmentParameterChangedEventHandler(RightButtonHandler);
        }
        #endregion

        #region Button Handler
        private void LeftButtonHandler(AdjustmentParameter param)
        {
            ReDrawPreview();
        }

        private void RightButtonHandler(AdjustmentParameter param)
        {
            ReDrawPreview();
        }

        private void ReDrawPreview()
        {
            AnaglyphConfiguration anaglyphConfig = new AnaglyphConfiguration();
            anaglyphConfig.LeftCalibrationInfo = adjustmentButtons1.Adjustment;
            anaglyphConfig.RightCalibrationInfo = adjustmentButtons2.Adjustment;
            anaglyphConfig.ViewPort = TempViewPort;
            anaglyphConfig.IsSwap = false;//Might add some variable later
            calibrationImageViewer1.WindowImage = ImageProcessor.GetAnaglyph(LeftImage, RightImage, anaglyphConfig);
        }
        
        #endregion

        #region External Form Control

        private Bitmap LeftOriginalImage;
        private Bitmap RightOriginalImage;
        private float ShrinkFactor = 1;
        private Rectangle TempViewPort;

        private Bitmap LeftImage;
        private Bitmap RightImage;

        public void InitializeCalibration(Bitmap LeftImage, Bitmap RightImage)
        {
            this.LeftOriginalImage = LeftImage;
            this.RightOriginalImage = RightImage;

            int oldWidth = LeftImage.Width;
            int oldHeight = LeftImage.Height;

            int newWidth = calibrationImageViewer1.LeftPortSlider.Maximum;
            int newHeight = (int)(((float)newWidth) * (((float)oldHeight) / ((float)oldWidth)));
            if (newHeight > calibrationImageViewer1.TopPortSliderInv.Maximum)
            {
                newHeight = calibrationImageViewer1.TopPortSliderInv.Maximum;
                newWidth = (int)(((float)newHeight) * (((float)oldWidth) / ((float)oldHeight)));
            }
            ShrinkFactor = ((float)oldWidth) / ((float)newWidth);
            TempViewPort = new Rectangle(0, 0, newWidth, newHeight);

            this.LeftImage = new Bitmap(newWidth, newHeight);
            this.RightImage = new Bitmap(newWidth, newHeight);

            Graphics g = Graphics.FromImage(this.LeftImage);
            g.DrawImage(LeftImage, new Rectangle(0, 0, newWidth, newHeight), new Rectangle(0, 0, oldWidth, oldHeight), GraphicsUnit.Pixel);
            g.Dispose();
            Graphics g2 = Graphics.FromImage(this.RightImage);
            g2.DrawImage(RightImage, new Rectangle(0, 0, newWidth, newHeight), new Rectangle(0, 0, oldWidth, oldHeight), GraphicsUnit.Pixel);
            g2.Dispose();

            adjustmentButtons1.Adjustment = new AdjustmentParameter() { ColourFilter = MainForm.AnaglyphConfig.LeftCalibrationInfo.ColourFilter, Transformation = new TransformFactor() { LeftShift = MainForm.AnaglyphConfig.LeftCalibrationInfo.Transformation.LeftShift, RotationAngle = MainForm.AnaglyphConfig.LeftCalibrationInfo.Transformation.RotationAngle, TopShift = MainForm.AnaglyphConfig.LeftCalibrationInfo.Transformation.TopShift, ZoomFactor = MainForm.AnaglyphConfig.LeftCalibrationInfo.Transformation.ZoomFactor } };
            adjustmentButtons1.Adjustment.Transformation.LeftShift = (int)(((float)adjustmentButtons1.Adjustment.Transformation.LeftShift) / ShrinkFactor);
            adjustmentButtons1.Adjustment.Transformation.TopShift = (int)(((float)adjustmentButtons1.Adjustment.Transformation.TopShift) / ShrinkFactor);
            adjustmentButtons2.Adjustment = new AdjustmentParameter() { ColourFilter = MainForm.AnaglyphConfig.RightCalibrationInfo.ColourFilter, Transformation = new TransformFactor() { LeftShift = MainForm.AnaglyphConfig.RightCalibrationInfo.Transformation.LeftShift, RotationAngle = MainForm.AnaglyphConfig.RightCalibrationInfo.Transformation.RotationAngle, TopShift = MainForm.AnaglyphConfig.RightCalibrationInfo.Transformation.TopShift, ZoomFactor = MainForm.AnaglyphConfig.RightCalibrationInfo.Transformation.ZoomFactor } };
            adjustmentButtons2.Adjustment.Transformation.LeftShift = (int)(((float)adjustmentButtons2.Adjustment.Transformation.LeftShift) / ShrinkFactor);
            adjustmentButtons2.Adjustment.Transformation.TopShift = (int)(((float)adjustmentButtons2.Adjustment.Transformation.TopShift) / ShrinkFactor);
            ReDrawPreview();
        }

        public void ResizeImage(Size NewSize)
        {
            adjustmentButtons1.Adjustment.Transformation.LeftShift = (int)(((float)adjustmentButtons1.Adjustment.Transformation.LeftShift) * ShrinkFactor);
            adjustmentButtons1.Adjustment.Transformation.TopShift = (int)(((float)adjustmentButtons1.Adjustment.Transformation.TopShift) * ShrinkFactor);
            adjustmentButtons2.Adjustment.Transformation.LeftShift = (int)(((float)adjustmentButtons2.Adjustment.Transformation.LeftShift) * ShrinkFactor);
            adjustmentButtons2.Adjustment.Transformation.TopShift = (int)(((float)adjustmentButtons2.Adjustment.Transformation.TopShift) * ShrinkFactor);

            //Lets calculate the new shrink factor

            int oldWidth = LeftOriginalImage.Width;
            int oldHeight = LeftOriginalImage.Height;

            int newWidth = calibrationImageViewer1.LeftPortSlider.Maximum;
            int newHeight = (int)(((float)newWidth) * (((float)oldHeight) / ((float)oldWidth)));
            if (newHeight > calibrationImageViewer1.TopPortSliderInv.Maximum)
            {
                newHeight = calibrationImageViewer1.TopPortSliderInv.Maximum;
                newWidth = (int)(((float)newHeight) * (((float)oldWidth) / ((float)oldHeight)));
            }
            ShrinkFactor = ((float)oldWidth) / ((float)newWidth);
            TempViewPort = new Rectangle(0, 0, newWidth, newHeight);

            LeftImage = new Bitmap(newWidth, newHeight);
            RightImage = new Bitmap(newWidth, newHeight);

            Graphics g = Graphics.FromImage(LeftImage);
            g.DrawImage(LeftOriginalImage, new Rectangle(0, 0, newWidth, newHeight), new Rectangle(0, 0, oldWidth, oldHeight), GraphicsUnit.Pixel);
            g.Dispose();
            Graphics g2 = Graphics.FromImage(RightImage);
            g2.DrawImage(RightOriginalImage, new Rectangle(0, 0, newWidth, newHeight), new Rectangle(0, 0, oldWidth, oldHeight), GraphicsUnit.Pixel);
            g2.Dispose();

            adjustmentButtons1.Adjustment.Transformation.LeftShift = (int)(((float)adjustmentButtons1.Adjustment.Transformation.LeftShift) / ShrinkFactor);
            adjustmentButtons1.Adjustment.Transformation.TopShift = (int)(((float)adjustmentButtons1.Adjustment.Transformation.TopShift) / ShrinkFactor);
            adjustmentButtons2.Adjustment.Transformation.LeftShift = (int)(((float)adjustmentButtons2.Adjustment.Transformation.LeftShift) / ShrinkFactor);
            adjustmentButtons2.Adjustment.Transformation.TopShift = (int)(((float)adjustmentButtons2.Adjustment.Transformation.TopShift) / ShrinkFactor);
            ReDrawPreview();
        }
        
        #endregion

        private void SaveImageButton_Click(object sender, EventArgs e)
        {
            //Create the anaglyphConfig
            AnaglyphConfiguration anaglyphConfig = new AnaglyphConfiguration();
            anaglyphConfig.LeftCalibrationInfo = adjustmentButtons1.Adjustment;
            anaglyphConfig.LeftCalibrationInfo.Transformation.LeftShift = (int)(((float)anaglyphConfig.LeftCalibrationInfo.Transformation.LeftShift) * ShrinkFactor);
            anaglyphConfig.LeftCalibrationInfo.Transformation.TopShift = (int)(((float)anaglyphConfig.LeftCalibrationInfo.Transformation.TopShift) * ShrinkFactor);
            anaglyphConfig.RightCalibrationInfo = adjustmentButtons2.Adjustment;
            anaglyphConfig.RightCalibrationInfo.Transformation.LeftShift = (int)(((float)anaglyphConfig.RightCalibrationInfo.Transformation.LeftShift) * ShrinkFactor);
            anaglyphConfig.RightCalibrationInfo.Transformation.TopShift = (int)(((float)anaglyphConfig.RightCalibrationInfo.Transformation.TopShift) * ShrinkFactor);

            anaglyphConfig.ViewPort = calibrationImageViewer1.ViewPort;
            int viewLeft = (int)(((float)anaglyphConfig.ViewPort.Left) * ShrinkFactor);
            int viewTop = (int)(((float)anaglyphConfig.ViewPort.Top) * ShrinkFactor);
            int viewWidth = (int)(((float)anaglyphConfig.ViewPort.Width) * ShrinkFactor);
            int viewHeight = (int)(((float)anaglyphConfig.ViewPort.Height) * ShrinkFactor);
            anaglyphConfig.ViewPort = new Rectangle(new Point(viewLeft, viewTop), new Size(viewWidth, viewHeight));

            anaglyphConfig.IsSwap = false;//Might add some variable later
            //anaglyph config created

            Bitmap bmp = ImageProcessor.GetAnaglyph(LeftOriginalImage, RightOriginalImage, anaglyphConfig);

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.OverwritePrompt = true;
            sfd.CheckPathExists = true;
            sfd.AddExtension=true;
            sfd.Filter = "Bitmap image|*.bmp|Png image|*.png|Jpeg image|*.jpg";
            sfd.FilterIndex = 0;
            System.Windows.Forms.DialogResult DR = sfd.ShowDialog();
            if (DR == System.Windows.Forms.DialogResult.OK)
            {
                string FileName = sfd.FileName;
                if (sfd.FilterIndex == 0)
                {
                    bmp.Save(FileName, System.Drawing.Imaging.ImageFormat.Bmp);
                }
                else if (sfd.FilterIndex == 1)
                {
                    bmp.Save(FileName, System.Drawing.Imaging.ImageFormat.Png);
                }
                else
                {
                    bmp.Save(FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
            }
            bmp.Dispose();

            //Restore to previous calibration state
            anaglyphConfig.LeftCalibrationInfo.Transformation.LeftShift = (int)(((float)anaglyphConfig.LeftCalibrationInfo.Transformation.LeftShift) / ShrinkFactor);
            anaglyphConfig.LeftCalibrationInfo.Transformation.TopShift = (int)(((float)anaglyphConfig.LeftCalibrationInfo.Transformation.TopShift) / ShrinkFactor);
            anaglyphConfig.RightCalibrationInfo.Transformation.LeftShift = (int)(((float)anaglyphConfig.RightCalibrationInfo.Transformation.LeftShift) / ShrinkFactor);
            anaglyphConfig.RightCalibrationInfo.Transformation.TopShift = (int)(((float)anaglyphConfig.RightCalibrationInfo.Transformation.TopShift) / ShrinkFactor);

        }

        private void AcceptCalibrationButton_Click(object sender, EventArgs e)
        {
            //Create the anaglyphConfig
            AnaglyphConfiguration anaglyphConfig = new AnaglyphConfiguration();
            anaglyphConfig.LeftCalibrationInfo = adjustmentButtons1.Adjustment;
            anaglyphConfig.LeftCalibrationInfo.Transformation.LeftShift = (int)(((float)anaglyphConfig.LeftCalibrationInfo.Transformation.LeftShift) * ShrinkFactor);
            anaglyphConfig.LeftCalibrationInfo.Transformation.TopShift = (int)(((float)anaglyphConfig.LeftCalibrationInfo.Transformation.TopShift) * ShrinkFactor);
            anaglyphConfig.RightCalibrationInfo = adjustmentButtons2.Adjustment;
            anaglyphConfig.RightCalibrationInfo.Transformation.LeftShift = (int)(((float)anaglyphConfig.RightCalibrationInfo.Transformation.LeftShift) * ShrinkFactor);
            anaglyphConfig.RightCalibrationInfo.Transformation.TopShift = (int)(((float)anaglyphConfig.RightCalibrationInfo.Transformation.TopShift) * ShrinkFactor);

            anaglyphConfig.ViewPort = calibrationImageViewer1.ViewPort;
            int viewLeft = (int)(((float)anaglyphConfig.ViewPort.Left) * ShrinkFactor);
            int viewTop = (int)(((float)anaglyphConfig.ViewPort.Top) * ShrinkFactor);
            int viewWidth = (int)(((float)anaglyphConfig.ViewPort.Width) * ShrinkFactor);
            int viewHeight = (int)(((float)anaglyphConfig.ViewPort.Height) * ShrinkFactor);
            anaglyphConfig.ViewPort = new Rectangle(new Point(viewLeft, viewTop), new Size(viewWidth, viewHeight));

            anaglyphConfig.IsSwap = false;//Might add some variable later
            //anaglyph config created
            MainForm.AnaglyphConfig = anaglyphConfig;
            Properties.Settings.Default.AnaglyphConfig = anaglyphConfig;
            Properties.Settings.Default.Save();
            DialogResult = System.Windows.Forms.DialogResult.OK;
        }

        private void RejectButton_Click(object sender, EventArgs e)
        {
            DialogResult = System.Windows.Forms.DialogResult.Cancel;
        }

        private void ImageSizeCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            int i = ImageSizeCombo.SelectedIndex;
            switch (i)
            {
                case 0:
                    this.Size = new Size(800, 535);
                    break;
                case 1:
                    this.Size = new Size(1040, 715);
                    break;
                case 2:
                    this.Size = new Size(1200, 835);
                    break;
                case 3:
                    this.Size = new Size(1600, 1135);
                    break;
                default:
                    this.Size = new Size(800, 535);
                    break;
            }
            Properties.Settings.Default.CalibrationWindowSize = i;
            Properties.Settings.Default.Save();
        }

    }
}
